// 27/04/2009 Dennis
class TimeSelector extends Control
{
  int minVal;
  int maxVal;
  long minTime;
  long maxTime;
  Date dateMin;
  Date dateMax;
  int scrollx1;
  int scrollx2;
  int state;
  int borderTolerance;
  boolean mouseDown;
  boolean lockedState = false;
  int scrollClickX1;
  int scrollClickX2;
  int dblClickCounter = 0;
  boolean expanding = false;
  boolean wasOver = false;
  
  // 27/04/2009 Dennis
  public TimeSelector()
  {
    height = 50;
    width = scrW;
    y = scrH - height;
    state = 0;
    borderTolerance = 5;
    scrollx1 = 0;
    scrollx2 = scrW;
  }
  
  public void setTimes(Date dateMin, Date dateMax)
  {
    minTime = dateMin.getTime();
    maxTime = dateMax.getTime();
    this.dateMin = dateMin;
    this.dateMax = dateMax;
  }
  
  // 27/04/2009 Dennis
  public void draw()
  {
    width = scrW;
    y = scrH - height;
    if(scrollx2 > width) {scrollx2 = width;}
    if(expanding)
    {
      if(scrollx1 < 7) scrollx1 = 0; else scrollx1 -= scrollx1 / 7;
      if(scrollx2 > width - 7) scrollx2 = width; else scrollx2 += (width - scrollx2) / 7;
      if(scrollx1 == 0 && scrollx2 == width) expanding = false;
    }
    noStroke();
    image(navbg, getX(), getY(), width, 50);
    
    int liney = getY() + height / 2;
    stroke(255);
    line(getX(), liney, getX() + width, liney);
    
    Date marker = new Date(dateMin.getYear() - 1, 0, 1);
    textFont(font1);
    String out;
    fill(255);
    while(marker.before(dateMax))
    {
      marker.setMonth(0);
      marker.setYear(marker.getYear() + 1);
      int x = (int)((marker.getTime() - minTime) * width / (maxTime - minTime) + getX());
      if(x >= 0 && x <= width)
      {
        line(x, liney, x, liney + 10);
        out = ""+(marker.getYear()+1900);
        text(out, x - textWidth(out) / 2, liney + 23);
      }
      for(int i = 0; i <= 11; i++)
      {
        marker.setMonth(i);
        x = (int)((marker.getTime() - minTime) * width / (maxTime - minTime) + getX());
        if(x >= 0 && x <= width)
        {
          line(x, liney, x, liney - 5);
          switch(marker.getMonth())
          {
            case 0: out = "J"; break;
            case 1: out = "F"; break;
            case 2: out = "M"; break;
            case 3: out = "A"; break;
            case 4: out = "M"; break;
            case 5: out = "J"; break;
            case 6: out = "J"; break;
            case 7: out = "A"; break;
            case 8: out = "S"; break;
            case 9: out = "O"; break;
            case 10: out = "N"; break;
            case 11: out = "D"; break;
            default: out = "";
          }
          text(out, x - textWidth(out) / 2, liney - 10);
        }
      }
    }
    
    noStroke();
    fill(color(#d0e4f0), state == 1 ? 100 : 80);
    
    stroke(#d0e4f0);
    line(getX() + scrollx1, getY(), getX() + scrollx1, getY() + height);
    line(getX() + scrollx2, getY(), getX() + scrollx2, getY() + height);
    noStroke();
    
    rect(getX() + scrollx1, getY(), scrollx2 - scrollx1, height);
    int tx = -1;
    Date selDate = null;
    if(state == 2)
    {
      tx = scrollx1;
      selDate = new Date(getMinTime());
    }
    else if(state == 3)
    {
      tx = scrollx2;
      selDate = new Date(getMaxTime());
    }
    if(tx > -1)
    {
      stroke(#ffa200);
      line(getX() + tx, getY(), getX() + tx, getY() + height);
      noStroke();
      fill(#ffa200);
      beginShape(TRIANGLES);
      vertex(getX() + tx - 5, getY());
      vertex(getX() + tx + 5, getY());
      vertex(getX() + tx, getY() + 5);
      vertex(getX() + tx - 5, getY() + height);
      vertex(getX() + tx + 5, getY() + height);
      vertex(getX() + tx, getY() + height - 5);
      endShape();
      
      out = dateformat.format(selDate);
      fill(#fefeff);
      stroke(#767676);
      textFont(font1);
      int rw = (int)textWidth(out) + 10;
      int rh = 25;
      int rx = tx;
      if(rx < 0) rx = 0;
      else if(rx + rw > width) rx = width - rw;
      int ry = mouseY - rh - 5;
      rect(rx, ry, rw, rh);
      fill(#767676);
      text(out, rx + 5, ry + 17);
    }
  }
  
  // 27/04/2009 Dennis
  public long getMinTime()
  {
    return (maxTime - minTime) * scrollx1 / width + minTime;
  }
  
  // 27/04/2009 Dennis
  public long getMaxTime()
  {
    return (maxTime - minTime) * scrollx2 / width + minTime;
  }
  
  // 27/04/2009 Dennis
  public boolean getEvent(int mx, int my, int mstate)
  {
    mx -= getX();
    my -= getY();
    boolean event = expanding;
    if(db.qryMin != getMinTime() || db.qryMax != getMaxTime())
    {
      event = true;
    }
    if(!wasOver && mstate == 1 && !lockedState)
      return event;
    wasOver = mouseOver(mx, my);
    if(dblClickCounter > 0)
      dblClickCounter--;
    
    if(mstate == 1 && lockedState)
      event = true;
    if(!lockedState)
      state = 0;
    if(lockedState)
    {
      scroll(mx, mstate);
    }
    else if(mouseOver(mx, my))
    {
      if(mstate == 1 && !mouseDown)
      {
        if(dblClickCounter > 0)
        {
          dblClickCounter = 0;
          expanding = true;
          mstate = 0;
          lockedState = false;
        }
        else
          dblClickCounter = 15;
      }
      if(mx >= scrollx1 + borderTolerance && mx <= scrollx2 - borderTolerance)
      {
        mouseCursor = 2;
        state = 1; // selected for move
        scroll(mx, mstate);
      }
      else if(mx >= scrollx1 - borderTolerance && mx < scrollx1 + borderTolerance)
      {
        mouseCursor = 1;
        state = 2; // selected left edge
        scroll(mx, mstate);
      }
      else if(mx >= scrollx2 - borderTolerance && mx < scrollx2 + borderTolerance)
      {
        mouseCursor = 1;
        state = 3; // selected right edge
        scroll(mx, mstate);
      }
    }
    mouseDown = mstate == 1;
    return event;
  }
  
  // 27/04/2009 Dennis
  private void scroll(int mx, int mstate)
  {
    int w = scrollx2 - scrollx1;
    if(mstate == 1 && !mouseDown)
    {
      scrollClickX1 = mx - scrollx1;
      scrollClickX2 = mx - scrollx2;
      lockedState = true;
    }
    if(mstate != 1)
      lockedState = false;
    if(mouseDown)
    {
      switch(state)
      {
        case 1: scrollx1 = mx - scrollClickX1; scrollx2 = mx - scrollClickX2; break;
        case 2: scrollx1 = mx - scrollClickX1; break;
        case 3: scrollx2 = mx - scrollClickX2;
      }
    }
    if(scrollx1 > scrollx2)
    {
      int temp = scrollx1;
      scrollx1 = scrollx2;
      scrollx2 = temp;
      temp = scrollClickX1;
      scrollClickX1 = scrollClickX2;
      scrollClickX2 = temp;
      if(state == 2)
      {
        state = 3;
      }
      else if(state == 3)
      {
        state = 2;
      }
    }
    if(w > width) w = width;
    if(scrollx1 < 0) {scrollx1 = 0; }
    if(scrollx2 > width) {scrollx2 = width;}
  }
}
